#include "ch32x035.h"
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "DevicesTime.h"
#include "DevicesDelay.h"
#include "DevicesQueue.h"
#include "DriverQC.h"


#define USB_QC_VOLTAGE_0V0          0
#define USB_QC_VOLTAGE_0V6          1
#define USB_QC_VOLTAGE_3V3          2

#define USB_QC_TYPE_SDP             0
#define USB_QC_TYPE_DCP             1
#define USB_QC_TYPE_CDP             2
#define USB_QC_TYPE_BC              3


/* ms */
uint32_t uiQcTimeGet(void)
{
    return (uint32_t)(lTimebaseGet() / 1000LL);
}

void vQcInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_16 | GPIO_Pin_17;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    AFIO->CTLR |= AFIO_CTLR_USB_IOEN | AFIO_CTLR_UDP_PUE | AFIO_CTLR_UDM_PUE;
}

void vQcDmSet(uint8_t ucValue)
{
    (ucValue != USB_QC_VOLTAGE_3V3) ? (AFIO->CTLR |= AFIO_CTLR_UDM_BC_VSRC) : (AFIO->CTLR &= ~AFIO_CTLR_UDM_BC_VSRC);
}

void vQcDpSet(uint8_t ucValue)
{
    (ucValue != USB_QC_VOLTAGE_3V3) ? (AFIO->CTLR |= AFIO_CTLR_UDP_BC_VSRC) : (AFIO->CTLR &= ~AFIO_CTLR_UDP_BC_VSRC);
}

uint8_t ucQcDmGet(void)
{
    return (AFIO->CTLR & AFIO_CTLR_UDM_BC_CMPO) != 0;
}

uint8_t ucQcDpGet(void)
{
    return (AFIO->CTLR & AFIO_CTLR_UDP_BC_CMPO) != 0;
}

void vQcRequest5V(void)
{
    vQcDmSet(USB_QC_VOLTAGE_0V0);
    vQcDpSet(USB_QC_VOLTAGE_0V6);
}

void vQcRequest9V(void)
{
    vQcDmSet(USB_QC_VOLTAGE_0V6);
    vQcDpSet(USB_QC_VOLTAGE_3V3);
}

void vQcRequest12V(void)
{
    vQcDmSet(USB_QC_VOLTAGE_0V6);
    vQcDpSet(USB_QC_VOLTAGE_0V6);
}

void vQcRequest20V(void)
{
    vQcDmSet(USB_QC_VOLTAGE_3V3);
    vQcDpSet(USB_QC_VOLTAGE_3V3);
}

uint8_t ucQcCheck(void)
{
    /* 在DP数据线上输出0.6V左右的电压，然后检测DM的电平状态 */
    vQcDmSet(USB_QC_VOLTAGE_0V0);
    vQcDpSet(USB_QC_VOLTAGE_0V6);
    vDelayMs(10);

    /* 如果 DM 电平呈现0状态，则说明供电端（Source）的DM、DP没有短接，可以判定Source为SDP，否则Source为DCP 或者 CDP */
    if(ucQcDmGet() == 0)
        return USB_QC_TYPE_SDP;


    /* 在DM数据线上输出0.6V左右的电压，然后检测DP的电平状态 */
    vQcDmSet(USB_QC_VOLTAGE_0V6);
    vQcDpSet(USB_QC_VOLTAGE_0V0);
    vDelayMs(10);

    /* 如果 DP 电平呈现0状态，则说明供电端（Source）为虚短状态，判断Source为CDP，否则Source为DCP */
    if(ucQcDpGet() == 0)
        return USB_QC_TYPE_CDP;


    /* 在DP数据线上输出0.6V左右的电压，然后检测DM的电平状态 */
    vQcDmSet(USB_QC_VOLTAGE_0V0);
    vQcDpSet(USB_QC_VOLTAGE_0V6);
    vDelayMs(135);


    /* 在DP上输出0.6V左右的电压，等待DMDP的短接释放，现象为DP电平为0.6V，DM下降到0V。此时说明BC1.2运行成功 */
    return (ucQcDmGet() != 0) ? USB_QC_TYPE_DCP : USB_QC_TYPE_BC;
}
